PCI Interrupt Not Assigned - interrupt

The legacy interrupt assignment for a PCI interface is receiving interrupt 0.
We are evaluating the Xilinx Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit. We have a PMC interface that is on a PCI-e carrier inserted into the PCI-e slot on the board.
When the driver is loaded the interrupt for the board is assigned interrupt 0 from the OS (Linux 16.0.4). Interrupt 0 is clearly not correct.
The device tree for PCI should be assigning interrupts. We do see the misc interrupt assigned, but the intx interrupt is not being reported, or rather is returning 0 from the OS.
How can we determine why the interrupt is not being reported? What changes can we make to determine where the problem lies?
Here is the device tree entry for pcie --
ZynqMP> fdt print /amba/pcie
pcie#fd0e0000 {
compatible = "xlnx,nwl-pcie-2.11";
status = "okay";
#address-cells = <0x00000003>;
#size-cells = <0x00000002>;
#interrupt-cells = <0x00000001>;
msi-controller;
device_type = "pci";
interrupt-parent = <0x00000004>;
interrupts = <0x00000000 0x00000076 0x00000004 0x00000000 0x00000075 0x00000004 0x00000000 0x00000074 0x00000004 0x00000000 0x00000073 0x00000004 0x00000000 0x00000072 0x00000004>;
interrupt-names = "misc", "dummy", "intx", "msi1", "msi0";
msi-parent = <0x00000023>;
reg = <0x00000000 0xfd0e0000 0x00000000 0x00001000 0x00000000 0xfd480000 0x00000000 0x00001000 0x00000080 0x00000000 0x00000000 0x01000000>;
reg-names = "breg", "pcireg", "cfg";
ranges = <0x02000000 0x00000000 0xe0000000 0x00000000 0xe0000000 0x00000000 0x10000000 0x43000000 0x00000006 0x00000000 0x00000006 0x00000000 0x00000002 0x00000000>;
interrupt-map-mask = <0x00000000 0x00000000 0x00000000 0x00000007>;
bus-range = <0x00000000 0x000000ff>;
interrupt-map = * 0x000000007ff8495c [0x00000060];
power-domains = <0x00000025>;
clocks = <0x00000003 0x00000017>;
xlnx,pcie-mode = "Root Port";
linux,phandle = <0x00000023>;
phandle = <0x00000023>;
legacy-interrupt-controller {
interrupt-controller;
#address-cells = <0x00000000>;
#interrupt-cells = <0x00000001>;
linux,phandle = <0x00000024>;
phandle = <0x00000024>;
};
};

Related

How does an ELF file determine the offset values of each segment?

This is the command I've done:
readelf -l helloworld
And this is the output:
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000002d8 0x00000000000002d8 R 0x8
INTERP 0x0000000000000318 0x0000000000400318 0x0000000000400318
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000004d0 0x00000000000004d0 R 0x1000
LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000
0x00000000000001d5 0x00000000000001d5 R E 0x1000
LOAD 0x0000000000002000 0x0000000000402000 0x0000000000402000
0x0000000000000148 0x0000000000000148 R 0x1000
LOAD 0x0000000000002e10 0x0000000000403e10 0x0000000000403e10
0x0000000000000214 0x0000000000000218 RW 0x1000
DYNAMIC 0x0000000000002e20 0x0000000000403e20 0x0000000000403e20
0x00000000000001d0 0x00000000000001d0 RW 0x8
NOTE 0x0000000000000338 0x0000000000400338 0x0000000000400338
0x0000000000000020 0x0000000000000020 R 0x8
NOTE 0x0000000000000358 0x0000000000400358 0x0000000000400358
0x0000000000000044 0x0000000000000044 R 0x4
GNU_PROPERTY 0x0000000000000338 0x0000000000400338 0x0000000000400338
0x0000000000000020 0x0000000000000020 R 0x8
GNU_EH_FRAME 0x0000000000002020 0x0000000000402020 0x0000000000402020
0x000000000000003c 0x000000000000003c R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000002e10 0x0000000000403e10 0x0000000000403e10
0x00000000000001f0 0x00000000000001f0 R 0x1
My question is, where do values like 0x0000000000000318 in the INTERP offset come from? And if you can get all the offset information for every segment, how can you get those values exactly if you have all the hex in the elf as a vector?
where do values like 0x0000000000000318 in the INTERP offset come from?
From the program header table, offset to which can be found in the ELF header.
And if you can get all the offset information for every segment, how can you get those values exactly if you have all the hex in the elf as a vector?
By "hex in the elf as a vector" you probably mean "I have the entire contents of the file in memory".
The answer is: you cast the pointer to in-memory data to Elf32_Ehdr* or Elf64_Ehdr* as appropriate, and go from there.
This answer has sample code which should get you started.

What is the difference between readelf -sD and readelf --dyn-syms

From readelf's manpage, I see that
--dyn-syms Display the dynamic symbol table
-s --syms Display the symbol table
-D --use-dynamic Use the dynamic section info when displaying symbols
So I think readelf -sD equals readelf --dyn-syms. However, when I test in CentOS 7, it gives the following result. I wonder why?
$readelf -sD a
Symbol table for image:
Num Buc: Value Size Type Bind Vis Ndx Name
6 0: 0000000000400580 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev
2 0: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
5 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit
4 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main
3 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev
1 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf
readelf --dyn-syms a
Symbol table '.dynsym' contains 7 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf#GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev#GLIBCXX_3.4 (3)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit#GLIBC_2.2.5 (2)
6: 0000000000400580 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev#GLIBCXX_3.4 (3)
P.S. a is compiled from the following code, with GCC 7.3.0 by g++ a.cpp -o a
#include <iostream>
int main() {
printf("aaa");
}

VkDescriptorSet overstepping dynamic UBO

I'm trying to implement a dynamic uniform buffer object to my project taking this code as an example. I'm new to the API, I have done the core of the program following this tutorial. At the moment I'm stuck with this issue:
validation layer: VkDescriptorSet 0x42bf70000000032[] bound as set #0 encountered the following validation error at vkCmdDrawIndexed() time: Dynamic descriptor in binding #2 index 0 uses buffer 9A90CE000000002B with dynamic offset 768 combined with offset 0 and range 32000 that oversteps the buffer size of 32000.
The error occurs for every occurance from this for loop (from createCommandBuffers()) (except the first one) :
for (uint32_t j = 0; j < OBJECT_INSTANCES; j++)
{
uint32_t dynamicOffset = j * static_cast<uint32_t>(dynamicAlignment);
std::cout << dynamicOffset << std::endl;
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[i], 1, &dynamicOffset);
vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
std::cout << "done" << std::endl;
}
(dynamicOffset seems correct and get incremented well by 256)
I really don't see what I have done wrong.. Do someone has an idea?
How the VkDescriptorSets are created:
void createDescriptorSets() {
std::vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
allocInfo.pSetLayouts = layouts.data();
descriptorSets.resize(swapChainImages.size());
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!");
}
size_t dubo_size = OBJECT_INSTANCES * dynamicAlignment;
std::cout << dubo_size << std::endl;
for (size_t i = 0; i < swapChainImages.size(); i++) {
VkDescriptorBufferInfo uniformBufferInfo = {};
uniformBufferInfo.buffer = uniformBuffers[i];
uniformBufferInfo.offset = 0;
uniformBufferInfo.range = sizeof(UniformBufferObject);
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = textureImageView;
imageInfo.sampler = textureSampler;
VkDescriptorBufferInfo dynamicUniformBufferInfo = {};
dynamicUniformBufferInfo.buffer = dynamicUniformBuffers[i];
dynamicUniformBufferInfo.offset = 0;
dynamicUniformBufferInfo.range = dubo_size;
std::array<VkWriteDescriptorSet, 3> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = descriptorSets[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &uniformBufferInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = descriptorSets[i];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &imageInfo;
descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[2].dstSet = descriptorSets[i];
descriptorWrites[2].dstBinding = 2;
descriptorWrites[2].dstArrayElement = 0;
descriptorWrites[2].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
descriptorWrites[2].descriptorCount = 1;
descriptorWrites[2].pBufferInfo = &dynamicUniformBufferInfo;
vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
}
}
How the buffers are created:
void createDynamicUniformBuffers()
{
VkPhysicalDeviceProperties prop;
vkGetPhysicalDeviceProperties(physicalDevice, &prop);
size_t minUboAlignment = prop.limits.minUniformBufferOffsetAlignment;
dynamicAlignment = sizeof(glm::mat4);
if (minUboAlignment > 0) {
dynamicAlignment = (dynamicAlignment + minUboAlignment - 1) & ~(minUboAlignment - 1);
}
VkDeviceSize bufferSize = OBJECT_INSTANCES * dynamicAlignment;
uboDataDynamic.model = (glm::mat4*)alignedAlloc(bufferSize, dynamicAlignment);
assert(uboDataDynamic.model);
std::cout << "minUniformBufferOffsetAlignment = " << minUboAlignment << std::endl;
std::cout << "dynamicAlignment = " << dynamicAlignment << std::endl;
dynamicUniformBuffers.resize(swapChainImages.size());
dynamicUniformBuffersMemory.resize(swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); i++) {
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, dynamicUniformBuffers[i], dynamicUniformBuffersMemory[i]);
}
}
And finally and bit more of the terminal:
minUniformBufferOffsetAlignment = 256
dynamicAlignment = 256
32000
0
done
256
validation layer: VkDescriptorSet 0x42bf70000000032[] bound as set #0 encountered the following validation error at vkCmdDrawIndexed() time: Dynamic descriptor in binding #2 index 0 uses buffer 9A90CE000000002B with dynamic offset 256 combined with offset 0 and range 32000 that oversteps the buffer size of 32000.
done
512
validation layer: VkDescriptorSet 0x42bf70000000032[] bound as set #0 encountered the following validation error at vkCmdDrawIndexed() time: Dynamic descriptor in binding #2 index 0 uses buffer 9A90CE000000002B with dynamic offset 512 combined with offset 0 and range 32000 that oversteps the buffer size of 32000.
done
768
validation layer: VkDescriptorSet 0x42bf70000000032[] bound as set #0 encountered the following validation error at vkCmdDrawIndexed() time: Dynamic descriptor in binding #2 index 0 uses buffer 9A90CE000000002B with dynamic offset 768 combined with offset 0 and range 32000 that oversteps the buffer size of 32000.
done
1024
validation layer: VkDescriptorSet 0x42bf70000000032[] bound as set #0 encountered the following validation error at vkCmdDrawIndexed() time: Dynamic descriptor in binding #2 index 0 uses buffer 9A90CE000000002B with dynamic offset 1024 combined with offset 0 and range 32000 that oversteps the buffer size of 32000.
done
1280
validation layer: VkDescriptorSet 0x42bf70000000032[] bound as set #0 encountered the following validation error at vkCmdDrawIndexed() time: Dynamic descriptor in binding #2 index 0 uses buffer 9A90CE000000002B with dynamic offset 1280 combined with offset 0 and range 32000 that oversteps the buffer size of 32000.
done
Fix: The range given to the VkDescriptorBufferInfo for the dynamic UBO was the issue. Works out when using dynamicUniformBufferInfo.range = VK_WHOLE_SIZE instead.

Eigen on STM32 works only until a certain size

I am trying to use Eigen C++ library on STM32F4 Discovery embedded board to perform some matrix operations in the future, specifically to do some kalman filtering on sensor data.
I tried linking against the standard c++ library and even tried to compile the program using g++ arm compiler.
typedef Eigen::Matrix<float, 10, 10> Matrix10d;
Matrix10d mat1 = Matrix10d::Constant(10, 10, 1);
Matrix10d mat2 = Matrix10d::Constant(10, 10, 2);
Matrix10d result;
result = mat1 * mat2;
I can compile the same code if the matrix size as been set to 7. If I cross that then the code wont compile and the eigen gives me a warning that
warning: argument 1 value '4294967295' exceeds maximum object size 2147483647
These are the partial error messages I am getting
n function 'throw_std_bad_alloc,
inlined from 'check_size_for_overflow at bla/bla/Eigen/src/Core/util/Memory.h:289:24
Here is the memory allocation in Linker script I am using
/*
* STM32F407xG memory setup.
* Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
*/
MEMORY
{
flash0 : org = 0x08000000, len = 1M
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
ram1 : org = 0x20000000, len = 112k /* SRAM1 */
ram2 : org = 0x2001C000, len = 16k /* SRAM2 */
ram3 : org = 0x00000000, len = 0
ram4 : org = 0x10000000, len = 64k /* CCM SRAM */
ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */
ram6 : org = 0x00000000, len = 0
ram7 : org = 0x00000000, len = 0
}
I am just running STM32F4 discovery board with unchanged Chibios configuration
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400
endif
Update
I was not able to reproduce this error anymore. The sad thing is that I didn't do anything to solve the issue.
arm-none-eabi-gcc -c -mcpu=cortex-m4 -O3 -Os -ggdb -fomit-frame-pointer -falign-functions=16 -ffunction-sections -fdata-sections -fno-common -flto -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant -Wall -Wextra -Wundef -Wstrict-prototypes -Wa,-alms=build/lst/ -DCORTEX_USE_FPU=TRUE -DCHPRINTF_USE_FLOAT=TRUE -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -MD -MP -MF .dep/build.d -I.
The above are the compiler options that I am using if anyone is interested.
Now I can multiply even 20x20 matrices with out any problem.
Matrix20d mat1 = Matrix20d::Constant(20, 20, 2);
// Multiply the matrix with a vector.
Vector20d vec = Vector20d::Constant(20, 1, 2);
Vector20d result;
systime_t startTime = chVTGetSystemTimeX();
result = mat1 * vec;
// Calculate the timedifference
systime_t endTime = chVTGetSystemTimeX();
systime_t timeDifference = chTimeDiffX(startTime, endTime);
chprintf(chp,"Time taken for the multiplication in milliseconds : %d\n", (int)timeDifference);
chprintf(chp, "System time : %d \n", startTime);
chprintf(chp, "Systime end : %d \n", endTime);
chprintf(chp, "Values in the vector : \n [");
for(Eigen::Index i=0; i < result.size();i++)
{
chprintf(chp, "%0.3f, ", result(i));
}
chprintf(chp, "] \n");
chThdSleepMilliseconds(1000);
It took about ~1ms to do the above computation.
I thought that there might be some problem with my compiler. So I tried with two versions of compilers
Version - 1
arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204]
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Version-2
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors 6-2017-q2-update) 6.3.1 20170620 (release) [ARM/embedded-6-branch revision 249437]
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

How can I use iCE40 4K block RAM in 512x8 read mode with IceStorm?

I am trying to figure out how to use the block RAM on my iCE40HX-8K Breakout Board. I would like to access it in a 512x8 configuration, which as far as I can tell from the documentation is supported by project IceStorm, but I haven't been able to get it to work like I expected.
If I understand correctly, initializing an SB_RAM40_4K primitive with the READ_MODE parameter set to 1 should set the block up in 512x8 read mode, which uses a 9 bit read address, and reads 8 bits of data at each address.
Here is the simplest example I could think of. It sets up an SB_RAM40_4K with some pre-initialized memory and reads straight to the pins of the on-board LED's.
hx8kboard.pcf
set_io leds[0] B5
set_io leds[1] B4
set_io leds[2] A2
set_io leds[3] A1
set_io leds[4] C5
set_io leds[5] C4
set_io leds[6] B3
set_io leds[7] C3
set_io clk J3
top.v
module top (
output [7:0] leds,
input clk
);
//reg [8:0] raddr = 8'd0;
reg [8:0] raddr = 8'd1;
SB_RAM40_4K #(
.INIT_0(256'h00000000000000000000000000000000000000000000000000000000_44_33_22_11),
.WRITE_MODE(1),
.READ_MODE(1)
) ram40_4k_512x8 (
.RDATA(leds),
.RADDR(raddr),
.RCLK(clk),
.RCLKE(1'b1),
.RE(1'b1),
.WADDR(8'b0),
.WCLK(1'b0),
.WCLKE(1'b0),
.WDATA(8'b0),
.WE(1'b0)
);
endmodule
LED output when raddr == 0
\|/ \|/
O O O O O O O O
LED output when raddr == 1
\|/ \|/ \|/ \|/
O O O O O O O O
I would think that address 1 in 512x8 mode would be the second 8 bits from RAM, which is 8'h22 or 8'b0010010. Instead I get 8'h33 or 8'b00110011. After a little experimentation, this seems to be the lower 8 bits of a 16 bit read.
I'm not sure where I went wrong. Any help understanding what's going on here would be appreciated. Thanks!
This question is not really about Yosys or Project IceStorm. The format used for the SB_RAM40_4K INIT_* parameters is the same for the IceStorm flow and the Lattice iCEcube2 flow. However, Lattice has done a very very bad job at documenting this format. Otherwise I'd just point you to the right Lattice document.. :)
You are interested in the 512x8 mode. First you need to know that in 512x8 mode only the even bits of .RDATA() and .WDATA() are used (not the 8 LSB bits, as your code suggests!).
The data in .INIT_* is stored as 16 16-bit words per parameter. The lowest 16-bit word in .INIT_0() contains the 8-bit word at addr 0 in its even bits and the 8-bit word at addr 256 in its odd bits.
The next 16-bit word in .INIT_0() contains words 1 and 257. The lowest 16-bits in .INIT_1() contain words 16 and 272, and so forth.
The easiest way to investigate this kind of stuff is probably to either read the SB_RAM40_4K simulation model in /usr/local/share/yosys/ice40/cells_sim.v, or simply let Yosys infer the memory and observe what yosys does. For example the following design:
module test(input clk, wen, input [8:0] addr, input [7:0] wdata, output reg [7:0] rdata);
reg [7:0] mem [0:511];
initial mem[0] = 255;
always #(posedge clk) begin
if (wen) mem[addr] <= wdata;
rdata <= mem[addr];
end
endmodule
Will produce the following output when run through yosys -p 'synth_ice40; write_verilog' test.v:
(* top = 1 *)
(* src = "test.v:1" *)
module test(clk, wen, addr, wdata, rdata);
(* src = "/usr/local/bin/../share/yosys/ice40/brams_map.v:255" *)
(* unused_bits = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" *)
wire [15:0] _0_;
(* src = "test.v:1" *)
input [8:0] addr;
(* src = "test.v:1" *)
input clk;
(* src = "test.v:1" *)
output [7:0] rdata;
(* src = "test.v:1" *)
input [7:0] wdata;
(* src = "test.v:1" *)
input wen;
(* src = "/usr/local/bin/../share/yosys/ice40/brams_map.v:277|/usr/local/bin/../share/yosys/ice40/brams_map.v:35" *)
SB_RAM40_4K #(
.INIT_0(256'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x1x1x1x1x1x1x1),
.INIT_1(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_2(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_3(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_4(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_5(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_6(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_7(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_8(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_9(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_A(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_B(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_C(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_D(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_E(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_F(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.READ_MODE(32'sd1),
.WRITE_MODE(32'sd1)
) \mem.0.0.0 (
.MASK(16'hxxxx),
.RADDR({ 2'h0, addr }),
.RCLK(clk),
.RCLKE(1'h1),
.RDATA({ _0_[15], rdata[7], _0_[13], rdata[6], _0_[11], rdata[5], _0_[9], rdata[4], _0_[7], rdata[3], _0_[5], rdata[2], _0_[3], rdata[1], _0_[1], rdata[0] }),
.RE(1'h1),
.WADDR({ 2'h0, addr }),
.WCLK(clk),
.WCLKE(wen),
.WDATA({ 1'hx, wdata[7], 1'hx, wdata[6], 1'hx, wdata[5], 1'hx, wdata[4], 1'hx, wdata[3], 1'hx, wdata[2], 1'hx, wdata[1], 1'hx, wdata[0] }),
.WE(1'h1)
);
endmodule
(Scroll all the way to the right to see the initialization pattern generated for the mem[0] = 255 initialization.)