Home > Community > Blogs > System Design and Verification > creating the zynq virtual platform including errata
 
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more conveniennt.

Register | Membership benefits
Get email delivery of the System Design and Verification blog (individual posts).
 

Email

* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

Creating the Zynq Virtual Platform, Including Errata

Comments(1)Filed under: embedded software, linux, SystemC, ip-xact, System Design and Verification, virtual platforms, Embedded Linux, Virtual System Platform, virtual prototoypes, Zynq, errata

Although I have never contributed any code to the Linux kernel, the headline We are all Linux developers now on linux today caught my eye. One of the things that amazes me is how many embedded products use Linux and how they deal with all of the complexity. Nearly every product has similar but different hardware, and keeping it all straight and shipping a product with working software in the dynamic world of Linux is impressive.

As a virtual platform developer these details hit me every so often, but I actually enjoy learning and finding connections to the greater software development world. This story is about creating a model of the PL310 L2 cache controller for the Zynq Virtual Platform I have previously described. At Cadence, we create Virtual Platform models from an IP-XACT description of each hardware block (I'll save the details of this flow for another day), but needless to say we sometimes encounter situations where gaps are revealed between the spec and what the Linux kernel actually does. Today, I hit one such situation.

While creating a SystemC model from the register specification of the PL310, I was running the Zynq Linux kernel, and noticed that the kernel was writing to a register in the PL310 that does not exist in the register summary, offset 0x740. We have checking built into all of our generated models that automatically flags such accesses. Originally, the Cadence engineers making our model creation tool thought this was a real error and would have the model return a bad status on the TLM-2.0 transaction, but I convinced them this was fairly common in the Linux kernel and crashing the kernel for a read or a write to an un-described register in a peripheral was bad and a warning was enough to trigger further investigation. I managed to dig around in the Zynq Linux tree and find the code in arch/arm/mm/cache-l2x0.c

static inline void cache_sync(void)
{
        void __iomem *base = l2x0_base;
 
#ifdef CONFIG_ARM_ERRATA_753970
        /* write to an unmmapped register */
        writel_relaxed(0, base + L2X0_DUMMY_REG);
#else
        writel_relaxed(0, base + L2X0_CACHE_SYNC);
#endif
        cache_wait(base + L2X0_CACHE_SYNC, 1);
}

Sure enough there was a write register called L2X0_DUMMY_REG which was defined as offset 0x740 in arch/arm/include/asm/hardware/cache-l2x0.h

#define L2X0_DUMMY_REG                  0x740

#ifdef CONFIG_ARM_ERRATA_753970

Tracing the ifdef for the errata back to the menuconfig, I found quite a long list of ARM errata, and sure enough one of them is checked. Using the help on each errata I was able to find the magic number of 753970.

Then I read that the sync issue is for version r3p0 of the PL310. Then going back to the Zynq Technical Reference Manual I checked to see that, sure enough, it includes version r3p0 of the PL310. The workaround to write the unmapped registers seems to apply here.

The good news about Virtual Platforms is that they don't have such issues about draining write buffers. It's also no problem to add the new dummy register at offset 0x740.

One of the nice features of the Cadence Virtual System Platform is that it can keep track of accesses to registers so you can see which registers are actually being used. As a test I decided to build the kernel with the errata workaround and without it, and see the difference in behavior and make sure both cases work fine for the PL310 model.

To turn on register profiling I used the command

ncsim> scprofile -on sc_main.bp_demo.zynq_ps.pl310

Then I ran the simulation until the Linux boot was complete and turned off using another scprofile command

ncsim> scprofile -off

When the profile is turned off the statistics are dumped out so we can see the access counts.

Here is the access count with the errata. You can see all of the write accesses of the dummy register at offset 0x740.

____________________________________________________________________________________________________
SCPROFILE : Register Access Count
----------------------------------------------------------------------------------------------------
Object                                                                  Read       Write       Total
----------------------------------------------------------------------------------------------------
>bp_demo.zynq_ps.zynq_ps_i.pl310...........................................5.......27995.......28000
 (Counter - Start: 0 s, End: 29785308360 ns)
  >>bp_demo.zynq_ps.zynq_ps_i.pl310.l2cache_bank...........................5.......27995.......28000
    (socket: bp_demo.zynq_ps.zynq_ps_i.pl310.tsocket)
      bp_demo.zynq_ps.zynq_ps_i.pl310.L2X0_DUMMY_REG.......................0.......22421.......22421
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg0_cache_id........................1...........0...........1
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg0_cache_type......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg12_addr_filtering_end.............0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg12_addr_filtering_start...........0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg15_debug_ctrl.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg15_power_ctrl.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg15_prefetch_ctrl..................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_aux_control.....................1...........1...........2
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_control.........................2...........1...........3
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_data_ram_control................0...........1...........1
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_tag_ram_control.................0...........1...........1
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter0.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter0_cfg.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter1.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter1_cfg.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter_ctrl.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_clear.......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_mask........................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_mask_status.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_raw_status..................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_cache_sync......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_index.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_inv_index.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_inv_pa....................0.........920.........920
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_inv_way...................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_pa........................0.........113.........113
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_way.......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_inv_pa..........................0........4536........4536
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_inv_way.........................1...........1...........2
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown0.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown1.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown2.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown3.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown4.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown5.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown6.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown7.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown0.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown1.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown2.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown3.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown4.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown5.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown6.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown7.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_lock_line_en....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_unlock_way......................0...........0...........0
____________________________________________________________________________________________________

 

Here is the access count without the workaround. You can see all of the write accesses to the normal cache sync register at offset 0x730.

____________________________________________________________________________________________________
SCPROFILE : Register Access Count
----------------------------------------------------------------------------------------------------
Object                                                                  Read       Write       Total
----------------------------------------------------------------------------------------------------
>bp_demo.zynq_ps.zynq_ps_i.pl310...........................................5.......27995.......28000
 (Counter - Start: 0 s, End: 26743271920 ns)
  >>bp_demo.zynq_ps.zynq_ps_i.pl310.l2cache_bank...........................5.......27995.......28000
    (socket: bp_demo.zynq_ps.zynq_ps_i.pl310.tsocket)
      bp_demo.zynq_ps.zynq_ps_i.pl310.L2X0_DUMMY_REG.......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg0_cache_id........................1...........0...........1
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg0_cache_type......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg12_addr_filtering_end.............0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg12_addr_filtering_start...........0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg15_debug_ctrl.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg15_power_ctrl.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg15_prefetch_ctrl..................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_aux_control.....................1...........1...........2
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_control.........................2...........1...........3
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_data_ram_control................0...........1...........1
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg1_tag_ram_control.................0...........1...........1
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter0.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter0_cfg.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter1.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter1_cfg.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_ev_counter_ctrl.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_clear.......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_mask........................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_mask_status.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg2_int_raw_status..................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_cache_sync......................0.......22421.......22421
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_index.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_inv_index.................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_inv_pa....................0.........920.........920
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_inv_way...................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_pa........................0.........113.........113
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_clean_way.......................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_inv_pa..........................0........4536........4536
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg7_inv_way.........................1...........1...........2
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown0.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown1.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown2.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown3.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown4.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown5.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown6.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_d_lockdown7.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown0.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown1.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown2.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown3.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown4.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown5.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown6.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_i_lockdown7.....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_lock_line_en....................0...........0...........0
      bp_demo.zynq_ps.zynq_ps_i.pl310.reg9_unlock_way......................0...........0...........0
____________________________________________________________________________________________________

Unfortunately, the list of registers is in alphabetical order, not address offset order, but you can see Virtual Platforms are a useful learning tool. It's interesting for me to encounter such situations to really understand how hardware and software work together. Access counts like these also show unused features, and can trigger questions about why certain registers are not accessed by software.

Just to see if there was any more information about this PL310 issue I did some searching and found that I was correct; it's not easy to keep track of all of this. Not too long ago somebody in the Linaro developers forum proposed to enable the workaround for the Pandaboard, but then there was some confusion about value returned in the ID register of the PL310 for the OMAP 4430 and it took a final confirmation from TI to state that the Pandaboard actually uses r2p0 of the PL310 so the errata doesn't apply.

Hats off to all of the engineers creating embedded Linux products (including the Zynq Linux team); it's hard to keep it all straight.

For now, I'll just keep trying to do my best to model hardware, errata and all.

Jason Andrews

Comments(1)

By Jakob Engblom on January 9, 2012
Interesting blog post! Typical story - hardware devices tend to accept pretty much any access thrown at it without anything bad happening at runtime. While a virtual platform written from specs and manuals pretty much is guaranteed to flag these. And flag them you should, since you never know if a bad access is a documented workaround, a poorly documented register, a defined location that does nothing but is explicitly reserved for future expansion - or an actual error in the driver that will bite you some time later.
I wrote a piece of this last year too,  at blogs.windriver.com/.../being-helpful-or-simply-correct.html

Leave a Comment


Name
E-mail (will not be published)
Comment
 I have read and agree to the Terms of use and Community Guidelines.
Community Guidelines
The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.