diff --git a/doc/cheby-ug.txt b/doc/cheby-ug.txt index b58623a0..83fd8bb8 100644 --- a/doc/cheby-ug.txt +++ b/doc/cheby-ug.txt @@ -289,6 +289,18 @@ or `RRESP`) is non-zero returning `SLVERR` (`0b10`). ** `wb-*`: In case of an error, the request is not acknowledged (`ACK` stays deasserted) but instead an error is returned (`ERR` is asserted). +`wmask`:: Enable the masking of the write data in a write request through the +dedicated bus features. The value is a boolean. By default this option is +disabled. Only the following bus interfaces are supported: + +** `apb-32`: Using the `PSTRB` signal a Byte-wise mask is applied. + +** `avalon-lite-32`: Using the `BE` signal a Byte-wise mask is applied. + +** `axi4-lite-32`: Using the `WSTRB` signal a Byte-wise mask is applied. + +** `wb-*`: Using the `SEL` signal a Byte-wise mask is applied. + === Registers A register uses one (usual case) or two (for 64-bit registers) words address. diff --git a/proto/cheby/expand_hdl.py b/proto/cheby/expand_hdl.py index be6da74f..e8ac150f 100644 --- a/proto/cheby/expand_hdl.py +++ b/proto/cheby/expand_hdl.py @@ -194,6 +194,8 @@ def expand_x_hdl_root(n, dct): n.hdl_pipeline = None n.hdl_bus_attribute = None n.hdl_iogroup = None + n.hdl_wmask = False + for k, v in dct.items(): if k in ['busgroup', 'reg_prefix', 'reg-prefix', 'block_prefix', 'block-prefix', @@ -202,6 +204,8 @@ def expand_x_hdl_root(n, dct): pass elif k == 'iogroup': n.hdl_iogroup = parser.read_text(n, k, v) + elif k == 'wmask': + n.hdl_wmask = parser.read_bool(n, k, v) elif k == 'bus-attribute': if v in ('Xilinx',): n.hdl_bus_attribute = v @@ -217,6 +221,7 @@ def expand_x_hdl_root(n, dct): else: parser.error("unhandled '{}' in x-hdl of root {}".format( k, n.get_path())) + # Default pipeline if n.hdl_pipeline is None: if n.bus == 'avalon-lite-32': @@ -225,10 +230,22 @@ def expand_x_hdl_root(n, dct): else: pl = ['wr-in', 'rd-out'] n.hdl_pipeline = pl + # Set name of the module. suffix = dct.get('name-suffix', '') n.hdl_module_name = n.name + suffix + expand_x_hdl_root_validate(n) + + +def expand_x_hdl_root_validate(r): + # Validate x-hdl attributes + if r.hdl_wmask and not any( + r.bus.startswith(bus) for bus in ["apb-", "avalon-lite-", "axi4-lite-", "wb-"] + ): + parser.error("Bus '{}' does not support the write mask feature".format(r.bus)) + + def expand_x_hdl_submap(n, dct): for k, _ in dct.items(): diff --git a/proto/cheby/hdl/genreg.py b/proto/cheby/hdl/genreg.py index c45156dd..c4dc246e 100644 --- a/proto/cheby/hdl/genreg.py +++ b/proto/cheby/hdl/genreg.py @@ -129,7 +129,7 @@ def assign_reg(self, then_stmts, else_stmts, off, ibus): reg, dat, mask = self.extract_reg_dat( off, self.field.h_reg, ibus.wr_dat, ibus.wr_sel ) - if self.root.c_wmask_reg and mask is not None: + if hasattr(self.root, "hdl_wmask") and self.root.hdl_wmask and mask is not None: then_stmts.append( HDLAssign( reg, @@ -154,7 +154,7 @@ def assign_reg(self, then_stmts, else_stmts, off, ibus): reg, dat, mask = self.extract_reg_dat( off, self.field.h_reg, ibus.wr_dat, ibus.wr_sel ) - if self.root.c_wmask_reg and mask is not None: + if hasattr(self.root, "hdl_wmask") and self.root.hdl_wmask and mask is not None: then_stmts.append( HDLAssign( reg, @@ -183,7 +183,11 @@ def connect_output(self, stmts, ibus): reg, dat, mask = self.extract_reg_dat( off, self.field.h_oport, ibus.wr_dat, ibus.wr_sel ) - if self.root.c_wmask_reg and mask is not None: + if ( + hasattr(self.root, "hdl_wmask") + and self.root.hdl_wmask + and mask is not None + ): stmts.append( HDLAssign( reg, @@ -219,7 +223,7 @@ def assign_reg(self, then_stmts, else_stmts, off, ibus): reg, dat, mask = self.extract_reg_dat( off, self.field.h_reg, ibus.wr_dat, ibus.wr_sel ) - if self.root.c_wmask_reg and mask is not None: + if hasattr(self.root, "hdl_wmask") and self.root.hdl_wmask and mask is not None: then_stmts.append( HDLAssign( reg, diff --git a/proto/cheby/layout.py b/proto/cheby/layout.py index 08f9b5d7..a29d5db0 100644 --- a/proto/cheby/layout.py +++ b/proto/cheby/layout.py @@ -649,14 +649,12 @@ def layout_bus(root, name): * c_align_reg * c_bussplit * c_buserr - * c_wmask_reg And deduce: * c_addr_word_bits * c_word_bits""" root.c_align_reg = True root.c_buserr = False root.c_bussplit = False - root.c_wmask_reg = False if name is None: # default root.c_word_size = 4 root.c_word_endian = 'big' @@ -735,7 +733,6 @@ def copy_bus(dst, src): dst.c_align_reg = src.c_align_reg dst.c_bussplit = src.c_bussplit dst.c_buserr = src.c_buserr - dst.c_wmask_reg = src.c_wmask_reg dst.c_addr_word_bits = src.c_addr_word_bits dst.c_word_bits = src.c_word_bits diff --git a/testfiles/tb/run.sh b/testfiles/tb/run.sh index dced1c91..f9acf1e0 100755 --- a/testfiles/tb/run.sh +++ b/testfiles/tb/run.sh @@ -175,24 +175,10 @@ build_wmask_any() name="$1" name_short="$2" - local file="../../proto/cheby/layout.py" - local setting="root\.c_wmask_reg" - - # Change default setting temporarily to enable write mask for all supporting interfaces - local prev_setting=$(grep "${setting}" "${file}" | awk '{print $NF}') - if [[ -n "${prev_setting}" && "${prev_setting}" == "False" ]]; then - sed -i "s|${setting} = ${prev_setting}|${setting} = True|" "${file}" - fi - echo "## Testing register write mask for interface '${name}'" sed -e '/bus:/s/BUS/'"${name}"'/' -e '/name:/s/NAME/'"${name_short}"'/' < wmask.cheby > wmask_${name_short}.cheby build_any "wmask_${name_short}" - - # Restore previous write mask setting - if [[ -n "${prev_setting}" && "${prev_setting}" == "False" ]]; then - sed -i "s|${setting} = True|${setting} = ${prev_setting}|" "${file}" - fi } # Build packages diff --git a/testfiles/tb/wmask.cheby b/testfiles/tb/wmask.cheby index 7bfb9c41..700df8f3 100644 --- a/testfiles/tb/wmask.cheby +++ b/testfiles/tb/wmask.cheby @@ -1,6 +1,8 @@ memory-map: bus: BUS name: wmask_NAME + x-hdl: + wmask: True children: - reg: name: reg1