VMM - RAL/vmm_ral_access.sv

RAL/vmm_ral_access.sv expanded source

00001 // 
00002 // -------------------------------------------------------------
00003 //    Copyright 2004-2008 Synopsys, Inc.
00004 //    All Rights Reserved Worldwide
00005 // 
00006 //    Licensed under the Apache License, Version 2.0 (the
00007 //    "License"); you may not use this file except in
00008 //    compliance with the License.  You may obtain a copy of
00009 //    the License at
00010 // 
00011 //        http://www.apache.org/licenses/LICENSE-2.0
00012 // 
00013 //    Unless required by applicable law or agreed to in
00014 //    writing, software distributed under the License is
00015 //    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00016 //    CONDITIONS OF ANY KIND, either express or implied.  See
00017 //    the License for the specific language governing
00018 //    permissions and limitations under the License.
00019 // -------------------------------------------------------------
00020 // 
00021 
00022 
00023 class vmm_ral_access extends `VMM_XACTOR;
00024    vmm_ral::path_e default_path = vmm_ral::BFM;  // Cannot be "DEFAULT"
00025 
00026    protected vmm_ral_block_or_sys model;
00027    
00028    protected vmm_rw_xactor rw_exec[string]; // One per domain
00029 
00030    extern function new();
00031 
00032    extern function void set_model(vmm_ral_block_or_sys model);
00033    extern function vmm_ral_block_or_sys get_model();
00034    extern function void add_xactor(vmm_rw_xactor xact,
00035                                    string        domain = "");
00036 
00037    extern task write(output vmm_rw::status_e status,
00038                      input  bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00039                      input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00040                      input  int                           n_bits = `VMM_RAL_DATA_WIDTH,
00041                      input  string                        domain = "",
00042                      input  int                           data_id = -1,
00043                      input  int                           scenario_id = -1,
00044                      input  int                           stream_id = -1);
00045 
00046    extern task read(output vmm_rw::status_e status,
00047                     input  bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00048                     output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00049                      input  int                           n_bits = `VMM_RAL_DATA_WIDTH,
00050                     input  string                         domain = "",
00051                     input  int                            data_id = -1,
00052                     input  int                            scenario_id = -1,
00053                     input  int                            stream_id = -1);
00054 
00055    extern task burst_write(output vmm_rw::status_e              status,
00056                            input  bit [`VMM_RAL_ADDR_WIDTH-1:0] start,
00057                            input  bit [`VMM_RAL_ADDR_WIDTH-1:0] incr,
00058                            input  bit [`VMM_RAL_ADDR_WIDTH-1:0] max,
00059                            input  bit [`VMM_RAL_DATA_WIDTH-1:0] data[],
00060                            input  vmm_data                      user = null,
00061                            input  int                           n_bits = `VMM_RAL_DATA_WIDTH,
00062                            input  string                        domain = "",
00063                            input  int                           data_id = -1,
00064                            input  int                           scenario_id = -1,
00065                            input  int                           stream_id = -1);
00066 
00067    extern task burst_read(output vmm_rw::status_e              status,
00068                           input  bit [`VMM_RAL_ADDR_WIDTH-1:0] start,
00069                           input  bit [`VMM_RAL_ADDR_WIDTH-1:0] incr,
00070                           input  bit [`VMM_RAL_ADDR_WIDTH-1:0] max,
00071                           input  int                           n_beats,
00072                           output bit [`VMM_RAL_DATA_WIDTH-1:0] data[],
00073                           input  vmm_data                      user = null,
00074                           input  int                           n_bits = `VMM_RAL_DATA_WIDTH,
00075                           input  string                        domain = "",
00076                           input  int                           data_id = -1,
00077                           input  int                           scenario_id = -1,
00078                           input  int                           stream_id = -1);
00079 
00080    extern virtual function bit set_by_name(input string                        name,
00081                                            input bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00082    extern virtual function bit get_by_name(input  string                        name,
00083                                            output bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00084 
00085    extern task write_by_name(output vmm_rw::status_e              status,
00086                              input  string                        name,
00087                              input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00088                              input  vmm_ral::path_e               path   = vmm_ral::DEFAULT,
00089                              input  string                        domain = "",
00090                              input  int                           data_id = -1,
00091                              input  int                           scenario_id = -1,
00092                              input  int                           stream_id = -1);
00093 
00094    extern task read_by_name(output vmm_rw::status_e              status,
00095                             input  string                        name,
00096                             output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00097                             input  vmm_ral::path_e               path   = vmm_ral::DEFAULT,
00098                             input  string                        domain = "",
00099                             input  int                           data_id = -1,
00100                             input  int                           scenario_id = -1,
00101                             input  int                           stream_id = -1);
00102 
00103    extern task write_mem_by_name(output vmm_rw::status_e              status,
00104                                  input  string                        name,
00105                                  input  bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00106                                  input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00107                                  input  vmm_ral::path_e               path   = vmm_ral::DEFAULT,
00108                                  input  string                        domain = "",
00109                                  input  int                           data_id = -1,
00110                                  input  int                           scenario_id = -1,
00111                                  input  int                           stream_id = -1);   
00112 
00113    extern task read_mem_by_name(output vmm_rw::status_e status,
00114                                 input  string                        name,
00115                                 input  bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00116                                 output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00117                                 input  vmm_ral::path_e               path = vmm_ral::DEFAULT,
00118                                 input  string                        domain = "",
00119                                 input  int                           data_id = -1,
00120                                 input  int                           scenario_id = -1,
00121                                 input  int                           stream_id = -1);
00122 
00123    /*local*/ extern function int
00124      Xget_physical_addressesX(bit [`VMM_RAL_ADDR_WIDTH-1:0]     base_addr,
00125                               bit [`VMM_RAL_ADDR_WIDTH-1:0]     mem_offset,
00126                               int unsigned                      n_bytes,
00127                               vmm_ral_block_or_sys              in_block,
00128                               string                            domain,
00129                               ref bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[]);
00130 endclass: vmm_ral_access
00131 
00132 
00133 function vmm_ral_access::new();
00134    super.new("RVM RAL Access", "Main");
00135 endfunction: new
00136 
00137 
00138 function void vmm_ral_access::set_model(vmm_ral_block_or_sys model);
00139    if (this.model != null) begin
00140       `vmm_error(this.log, "A RAL abstraction model has already been associated with this RAL access interface");
00141       return;
00142    end
00143 
00144    this.model = model;
00145 
00146    // Register this RAL access object with the RAL model
00147    model.Xregister_ral_accessX(this);
00148 endfunction: set_model
00149 
00150 
00151 function vmm_ral_block_or_sys vmm_ral_access::get_model();
00152    get_model = this.model;
00153 endfunction: get_model
00154 
00155 
00156 function void vmm_ral_access::add_xactor(vmm_rw_xactor xact,
00157                                          string        domain);
00158    if (this.model == null) begin
00159       `vmm_error(this.log, "A RAL abstraction model has not yet been associated with this RAL access interface");
00160       return;
00161    end
00162 
00163    // Check if the specified domain matches a domain in the model
00164    begin
00165       string domains[];
00166       bit found = 0;
00167 
00168       model.get_domains(domains);
00169       foreach (domains[i]) begin
00170          if (domains[i] == domain) begin
00171             found = 1;
00172             break;
00173          end
00174       end
00175       if (!found) begin
00176          `vmm_error(this.log, $psprintf("Domain \"%s\" does not exist in RAL model",
00177                                         domain));
00178          if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin
00179             string msg;
00180             this.log.text($psprintf("Domain \"%s\" does not exist in RAL model \"%s\"",
00181                                    domain, this.model.get_name()));
00182             msg = "Available domains are:";
00183             foreach (domains[i]) begin
00184                $sformat(msg, "%s \"%s\"", msg, domains[i]);
00185             end
00186             this.log.text(msg);
00187             this.log.end_msg();
00188          end
00189          return;
00190       end
00191    end
00192 
00193    if (this.rw_exec.exists(domain)) begin
00194       `vmm_error(this.log, $psprintf("Transactor for domain \"%s\" already exists",
00195                                      domain));
00196    end
00197    else begin
00198       this.rw_exec[domain] = xact;
00199 
00200       // Make sure transactor is started
00201       xact.start_xactor();
00202    end
00203 endfunction: add_xactor
00204 
00205 
00206 task vmm_ral_access::write(output vmm_rw::status_e              status,
00207                            input  bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00208                            input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00209                            input  int                           n_bits,
00210                            input  string                        domain,
00211                            input  int                           data_id,
00212                            input  int                           scenario_id,
00213                            input  int                           stream_id);
00214    status = vmm_rw::ERROR;
00215    
00216    if (!this.rw_exec.exists(domain)) begin
00217       `vmm_error(this.log, $psprintf("No transactor available to physically access domain \"%s\".",
00218                                      domain));
00219       return;
00220    end
00221 
00222    `vmm_trace(this.log, $psprintf("Writing 'h%h at 'h%h via domain \"%s\"...",
00223                                   data, addr, domain));
00224 
00225    begin
00226       vmm_rw_access rw = new;
00227 
00228       rw.data_id     = data_id;
00229       rw.scenario_id = scenario_id;
00230       rw.stream_id   = stream_id;
00231 
00232       rw.kind = vmm_rw::WRITE;
00233       rw.addr = addr;
00234       rw.data = data;
00235       rw.n_bits = n_bits;
00236       this.rw_exec[domain].exec_chan.put(rw);
00237 
00238       status = rw.status;
00239    end
00240 endtask: write
00241 
00242 
00243 task vmm_ral_access::read(output vmm_rw::status_e              status,
00244                           input  bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00245                           output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00246                           input  int                           n_bits,
00247                           input  string                        domain,
00248                           input  int                           data_id,
00249                           input  int                           scenario_id,
00250                           input  int                           stream_id);
00251    status = vmm_rw::ERROR;
00252    
00253    if (!this.rw_exec.exists(domain)) begin
00254       `vmm_error(this.log, $psprintf("No transactor available to physically access domain \"%s\".",
00255                                      domain));
00256       return;
00257    end
00258 
00259    begin
00260       vmm_rw_access rw = new;
00261 
00262       rw.data_id     = data_id;
00263       rw.scenario_id = scenario_id;
00264       rw.stream_id   = stream_id;
00265 
00266       rw.kind   = vmm_rw::READ;
00267       rw.addr   = addr;
00268       rw.n_bits = n_bits;
00269       this.rw_exec[domain].exec_chan.put(rw);
00270 
00271       data = rw.data;
00272       status = rw.status;
00273    end
00274 
00275    `vmm_trace(this.log, $psprintf("Read 'h%h from 'h%h via domain \"%s\"...",
00276                                   data, addr, domain));
00277 
00278 endtask: read
00279 
00280 
00281 task vmm_ral_access::burst_write(output vmm_rw::status_e              status,
00282                                  input  bit [`VMM_RAL_ADDR_WIDTH-1:0] start,
00283                                  input  bit [`VMM_RAL_ADDR_WIDTH-1:0] incr,
00284                                  input  bit [`VMM_RAL_ADDR_WIDTH-1:0] max,
00285                                  input  bit [`VMM_RAL_DATA_WIDTH-1:0] data[],
00286                                  input  vmm_data                      user,
00287                                  input  int                           n_bits,
00288                                  input  string                        domain,
00289                                  input  int                           data_id,
00290                                  input  int                           scenario_id,
00291                                  input  int                           stream_id);
00292    status = vmm_rw::ERROR;
00293    
00294    if (!this.rw_exec.exists(domain)) begin
00295       `vmm_error(this.log, $psprintf("No transactor available to physically access domain \"%s\".",
00296                                      domain));
00297       return;
00298    end
00299 
00300    begin
00301       vmm_rw_burst rw = new;
00302 
00303       rw.data_id     = data_id;
00304       rw.scenario_id = scenario_id;
00305       rw.stream_id   = stream_id;
00306 
00307       rw.kind      = vmm_rw::WRITE;
00308       rw.addr      = start;
00309       rw.incr_addr = incr;
00310       rw.max_addr  = max;
00311       rw.n_beats   = data.size();
00312       rw.n_bits    = n_bits;
00313       rw.user_data = user;
00314 
00315       rw.data = new [rw.n_beats];
00316       foreach (data[i]) rw.data[i] = data[i];
00317 
00318       this.rw_exec[domain].exec_chan.put(rw);
00319 
00320       status = rw.status;
00321    end
00322 
00323    `vmm_trace(this.log, $psprintf("Burst-wrote %0d data from ['h%h+'h%h %%'h%h] via domain \"%s\"...",
00324                                   data.size(), start, incr, max, domain));
00325 
00326 endtask: burst_write
00327 
00328 
00329 task vmm_ral_access::burst_read(output vmm_rw::status_e              status,
00330                                 input  bit [`VMM_RAL_ADDR_WIDTH-1:0] start,
00331                                 input  bit [`VMM_RAL_ADDR_WIDTH-1:0] incr,
00332                                 input  bit [`VMM_RAL_ADDR_WIDTH-1:0] max,
00333                                 input  int                           n_beats,
00334                                 output bit [`VMM_RAL_DATA_WIDTH-1:0] data[],
00335                                 input  vmm_data                      user,
00336                                 input  int                           n_bits,
00337                                 input  string                        domain,
00338                                 input  int                           data_id,
00339                                 input  int                           scenario_id,
00340                                 input  int                           stream_id);
00341    status = vmm_rw::ERROR;
00342    
00343    if (!this.rw_exec.exists(domain)) begin
00344       `vmm_error(this.log, $psprintf("No transactor available to physically access domain \"%s\".",
00345                                      domain));
00346       return;
00347    end
00348 
00349    begin
00350       vmm_rw_burst rw = new;
00351 
00352       rw.data_id     = data_id;
00353       rw.scenario_id = scenario_id;
00354       rw.stream_id   = stream_id;
00355 
00356       rw.kind      = vmm_rw::READ;
00357       rw.addr      = start;
00358       rw.incr_addr = incr;
00359       rw.max_addr  = max;
00360       rw.n_beats   = n_beats;
00361       rw.n_bits    = n_bits;
00362       rw.user_data = user;
00363 
00364       this.rw_exec[domain].exec_chan.put(rw);
00365 
00366       data = new [rw.data.size()];
00367       foreach (data[i]) data[i] = rw.data[i];
00368       status = rw.status;
00369    end
00370 
00371    `vmm_trace(this.log, $psprintf("Burst-read %0d data from ['h%h+'h%h %%'h%h] via domain \"%s\"...",
00372                                   data.size(), start, incr, max, domain));
00373 
00374 endtask: burst_read
00375 
00376 
00377 function bit vmm_ral_access::set_by_name(string                        name,
00378                                          bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00379    vmm_ral_reg rg;
00380 
00381    set_by_name = 0;
00382    rg = this.model.get_reg_by_name(name);
00383    if (rg == null) return 0;
00384 
00385    rg.set(value);
00386    set_by_name = 1;
00387 endfunction: set_by_name
00388 	
00389 
00390 function bit vmm_ral_access::get_by_name(input string                         name,
00391                                          output bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00392    vmm_ral_reg rg;
00393 
00394    get_by_name = 0;
00395    rg = this.model.get_reg_by_name(name);
00396    if (rg == null) return 0;
00397 
00398    value = rg.get();
00399    get_by_name = 1;
00400 endfunction: get_by_name
00401 	
00402 
00403 task vmm_ral_access::write_by_name(output vmm_rw::status_e              status,
00404                                    input  string                        name,
00405                                    input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00406                                    input  vmm_ral::path_e               path,
00407                                    input  string                        domain,
00408                                    input  int                           data_id,
00409                                    input  int                           scenario_id,
00410                                    input  int                           stream_id);
00411    vmm_ral_reg rg;
00412 
00413    status = vmm_rw::ERROR;
00414    rg = this.model.get_reg_by_name(name);
00415    if (rg == null) return;
00416 
00417    rg.write(status, data, path, domain, data_id, scenario_id, stream_id);
00418 endtask: write_by_name
00419 
00420 
00421 task vmm_ral_access::read_by_name(output vmm_rw::status_e              status,
00422                                   input  string                        name,
00423                                   output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00424                                   input  vmm_ral::path_e               path,
00425                                   input  string                        domain,
00426                                   input  int                           data_id,
00427                                   input  int                           scenario_id,
00428                                   input  int                           stream_id);
00429    vmm_ral_reg rg;
00430 
00431    status = vmm_rw::ERROR;
00432    rg = this.model.get_reg_by_name(name);
00433    if (rg == null) return;
00434 
00435    rg.read(status, data, path, domain, data_id, scenario_id, stream_id);
00436 endtask: read_by_name
00437 
00438 
00439 task vmm_ral_access::write_mem_by_name(output vmm_rw::status_e              status,
00440                                        input  string                        name,
00441                                        input  bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00442                                        input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00443                                        input  vmm_ral::path_e               path,
00444                                        input  string                        domain,
00445                                        input  int                           data_id,
00446                                        input  int                           scenario_id,
00447                                        input  int                           stream_id);
00448    vmm_ral_mem mem;
00449 
00450    status = vmm_rw::ERROR;
00451    mem = this.model.get_mem_by_name(name);
00452    if (mem == null) return;
00453 
00454    mem.write(status, offset, data, path, domain, data_id, scenario_id, stream_id);
00455 endtask: write_mem_by_name
00456 
00457 
00458 task vmm_ral_access::read_mem_by_name(output vmm_rw::status_e              status,
00459                                       input  string                        name,
00460                                       input  bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00461                                       output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00462                                       input  vmm_ral::path_e               path,
00463                                       input  string                        domain,
00464                                       input  int                           data_id,
00465                                       input  int                           scenario_id,
00466                                       input  int                           stream_id);
00467    vmm_ral_mem mem;
00468 
00469    status = vmm_rw::ERROR;
00470    mem = this.model.get_mem_by_name(name);
00471    if (mem == null) return;
00472 
00473    mem.read(status, offset, data, path, domain, data_id, scenario_id, stream_id);
00474 endtask: read_mem_by_name
00475 
00476 
00477 //
00478 // Identify the sequence of addresses that must be accessed physically
00479 // to access the specified number of bytes at the specified address
00480 // within the specified block or system. Returns the number of bytes
00481 // of valid data in each access.
00482 //
00483 // Returns a list of address in little endian order, with the granularity
00484 // of the top-level system
00485 //
00486 // A register is specified as a base address with mem_indx == 0.
00487 // A location within a memory is specified as an index from a base address.
00488 //
00489 function int vmm_ral_access::Xget_physical_addressesX(bit [`VMM_RAL_ADDR_WIDTH-1:0]     base_addr,
00490                                                       bit [`VMM_RAL_ADDR_WIDTH-1:0]     mem_offset,
00491                                                       int unsigned                      n_bytes,
00492                                                       vmm_ral_block_or_sys              in_block,
00493                                                       string                            domain,
00494                                                       ref bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[]);
00495    int bus_width = in_block.get_n_bytes(domain);
00496    bit [`VMM_RAL_ADDR_WIDTH-1:0] local_addr[];
00497    vmm_ral_block_or_sys          parent = in_block.get_parent();
00498 
00499    addr = new [0];
00500    
00501    if (n_bytes <= 0) begin
00502       `vmm_fatal(this.log, $psprintf("Cannot access %0d bytes. Must be greater than 0",
00503                                      n_bytes));
00504       return 0;
00505    end
00506 
00507    // First, identify the addresses within the block/system
00508    if (n_bytes <= bus_width) begin
00509       local_addr = new [1];
00510       local_addr[0] = base_addr + mem_offset;
00511    end else begin
00512       int n;
00513 
00514       n = ((n_bytes-1) / bus_width) + 1;
00515       local_addr = new [n];
00516       
00517       base_addr = base_addr + mem_offset * n;
00518 
00519       case (in_block.get_endian(domain))
00520          vmm_ral::LITTLE_ENDIAN: begin
00521             foreach (local_addr[i]) begin
00522                local_addr[i] = base_addr + i;
00523             end
00524          end
00525          vmm_ral::BIG_ENDIAN: begin
00526             foreach (local_addr[i]) begin
00527                n--;
00528                local_addr[i] = base_addr + n;
00529             end
00530          end
00531          vmm_ral::LITTLE_FIFO: begin
00532             foreach (local_addr[i]) begin
00533                local_addr[i] = base_addr;
00534             end
00535          end
00536          vmm_ral::BIG_FIFO: begin
00537             foreach (local_addr[i]) begin
00538                local_addr[i] = base_addr;
00539             end
00540          end
00541          default: begin
00542             `vmm_error(this.log, $psprintf("Block has no specified endianness. Cannot access %0d bytes register via its %0d byte \"%s\" interface",
00543                                            n_bytes, in_block.get_n_bytes(domain), domain));
00544          end
00545       endcase
00546    end
00547 
00548 
00549    // Then translate these addresses in the parent's space
00550    if (parent == null) begin
00551       // This is the top-most system/block!
00552       addr = new [local_addr.size()] (local_addr);
00553    end else begin
00554       bit [`VMM_RAL_ADDR_WIDTH-1:0] sys_addr[];
00555       bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr;
00556       string                        up_domain;
00557       int w, k;
00558 
00559       up_domain = in_block.get_parent_domain(domain);
00560 
00561       // Scale the consecutive local address in the system's granularity
00562       if (bus_width < parent.get_n_bytes(up_domain)) k = 1;
00563       else k = ((bus_width-1) / parent.get_n_bytes(up_domain)) + 1;
00564 
00565       base_addr = in_block.get_base_addr(domain);
00566       foreach (local_addr[i]) begin
00567          int n = addr.size();
00568          
00569          w = this.Xget_physical_addressesX(base_addr + local_addr[i] * k, 0,
00570                                            bus_width, parent, up_domain,
00571                                            sys_addr);
00572 
00573          addr = new [n + sys_addr.size()] (addr);
00574          foreach (sys_addr[j]) begin
00575             addr[n+j] = sys_addr[j];
00576          end
00577       end
00578       // The width of each access is the minimum of this block or the system's width
00579       if (w < bus_width) bus_width = w;
00580    end
00581 
00582    Xget_physical_addressesX = bus_width;
00583 endfunction: Xget_physical_addressesX