poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/1] pickles: Add new PCI Pickle


From: Darshit Shah
Subject: Re: [PATCH 1/1] pickles: Add new PCI Pickle
Date: Wed, 18 Sep 2024 00:27:56 +0200

Hi Mohammed,

Thanks for the review. Some responses inline...

On Tue, Sep 17, 2024, at 23:23, Mohammad-Reza Nabipoor wrote:
> Hi Darshit.
>
> Thank you for the patch.
>
>
> On Tue, Sep 17, 2024 at 08:33:42PM GMT, Darshit Shah wrote:
>> diff --git a/pickles/pci/pci_common.pk b/pickles/pci/pci_common.pk
>> new file mode 100644
>> index 0000000..4e91745
>> --- /dev/null
>> +++ b/pickles/pci/pci_common.pk
> [...]
>> +/**
>> + * Basic Registers
>> + */
>> +type reg_32 = uint<32>;
>> +type reg_16 = uint<16>;
>> +type reg_8 = uint<8>;
>
>
> Do we really need these types and uint<...> is not readable enough?
> If yes, please use names like `PCI_Reg32`, `PCI_Reg16` and `PCI_Reg8`.
>
It's not strictly necessary. I started writing this for a personal project and 
found the reg_* format more readable.
But I'm getting rid of it in favour of just using the native data types.

>
>> +
>> +//  While the PCI base specification differentiates between RsvdZ and 
>> RsvdP, we
>> +//  don't need that in Poke. The only difference between the two is what 
>> happens
>> +//  when you write to the bit, which is not something our representation 
>> needs
>> +//  to care about.
>> +type rsvdz = struct bit {
>> +    bit rsvdz == 0x0;
>> +    method _print = void:
>> +    {
>> +        print "rsvdz: 0";
>> +    }
>> +};
>
>
> We use the following code style:
>
> type PIC_RsvdZ =
>   struct
>     {
>       uint<1> rsvdz == 0;
>
>       // ...
>     };
>
> And `bit' is defined in `std-types.pk' file.
> This file is not loaded by some users of `libpoke' (like `gdb' integration).
> To make this pickle also useful for those applications, it's better to not use
> these "Standard Types".

This hurts the most. `bit` as a data type is a lot more readable than 
`uint<1>`. But for the moment,
I'm switching to using the uint directly.

Despite having removed the 3 definitions, i'm still keeping the file, since it 
will come in handy in the future
when I extend the pickle to also describe the various capabilities

>
>> -- 
>> 2.46.1
>> 
>> 
>> 
>> diff --git a/pickles/pci/pci.pk b/pickles/pci/pci.pk
>> new file mode 100644
>> index 0000000..10fb5ac
>> --- /dev/null
>> +++ b/pickles/pci/pci.pk
>> +
>> +type PCI_Command = struct reg_16 {
>> +    rsvdz;
>> +    rsvdz;
>> +    rsvdz;
>> +    rsvdz;
>> +    rsvdz;
>> +    bit int_disable;
>> +    bit fast_b2b_tx_enable == 0b0;
>
>
> Instead of `0b0' you can use `0' or `0T' or `0t`.
> `0T' and `0t' are of type `uint<1>'.
> `0' and `0b0' are of type `int<32>' (which is compatible due to implicit
> conversions).

Done
>
>
>> +    bit serr_enable;
>> +    bit idsel_stepping == 0b0;
>> +    bit parity_error_response;
>> +    bit vga_palette_snoop == 0b0;
>> +    bit mem_write_invalidate == 0b0;
>> +    bit sp_cycle_enable == 0b0;
>> +    bit bus_master_enable;
>> +    bit mem_enable;
>> +    bit io_enable;
>> +};
>> +
>> +type PCI_Status = struct reg_16 {
>> +    bit parity_error;
>> +    bit sig_sys_error;
>> +    bit rcvd_master_abort;
>> +    bit rcvd_target_abort;
>> +    bit sig_target_abort;
>> +    uint<2> devsel_timing == 0 as uint<2>;
>
> The `as uint<2>' is not necessary.

Done
>
>> +    bit master_data_parity_error;
>> +    bit fast_b2b_tx_cap;
>> +    rsvdz;
>> +    bit Mhz66_cap == 0b0;
>> +    bit cap_list;
>> +    bit int_status;
>> +    rsvdz;
>> +    rsvdz;
>> +    bit imm_readiness;
>> +};
>> +
>> +type PCI_Hdr_Type = struct reg_8 {
>> +    uint<7> hdr_layout;
>> +    bit multi_fn;
>> +};
>> +
>> +type PCI_BAR = struct {
>> +    reg_32;
>> +};
>> +
>> +type PCI_Type0 = struct {
>> +    PCI_BAR[6] bars;
>> +    reg_32 cardbus_cis_ptr == 0x0U;
>> +    reg_16 subsystem_vendor_id;
>> +    reg_16 subsystem_id;
>> +    reg_32 exp_rom_base_addr;
>> +    offset<reg_8,B> cap_ptr;
>> +    uint<56> rsvdz == 0;
>> +    reg_8 int_line;
>> +    reg_8 int_pin;
>> +    reg_8 min_gnt;
>> +    reg_8 max_lat;
>> +};
>
>
> It is a good practice to add a size assertion after defining these
> types like: `assert (#PCI_Type0 == 48#B);'
> ```
>
Done. And thanks since this found a bug in my definitions
>
>> +
>> +type PCI_Type1  = struct {
>> +    PCI_BAR bar_0;
>> +    PCI_BAR bar_1;
>> +    reg_8 primary_bus_nr;
>> +    reg_8 sec_bus_nr;
>> +    reg_8 sub_bus_nr;
>> +    reg_8 sec_lat_timer;
>> +    reg_8 io_base;
>> +    reg_8 io_limit;
>> +    reg_16 sec_status;
>> +    reg_16 mem_base;
>> +    reg_16 mem_limit;
>> +    reg_16 prefetch_mem_base;
>> +    reg_16 prefetch_mem_limit;
>> +    reg_32 prefetch_mem_base_upper;
>> +    reg_32 prefetch_mem_limit_upper;
>> +    reg_16 io_base_upper;
>> +    reg_16 io_base_limit;
>> +    offset<reg_16,B> cap_ptr;
>> +    uint<24> rsvdz == 0;
>> +    reg_32 exp_rom_base;
>> +    reg_8 int_line;
>> +    reg_8 int_pin;
>> +    reg_16 bridge_ctrl;
>> +};
>> +
>> +
>> +type PCI_Config_Space = struct {
>> +    reg_16 vendor;
>> +    reg_16 device;
>> +    PCI_Command command;
>> +    PCI_Status status;
>> +    reg_8 revision_id;
>> +    uint<24> class_code;
>> +    reg_8 cache_line_size;
>> +    reg_8 pri_lat_timer == 0;
>> +    PCI_Hdr_Type header;
>> +    reg_8 BIST;
>> +    if (header.hdr_layout == 0b0)
>> +        PCI_Type0 endpt_specific_data;
>> +    if (header.hdr_layout == 0b1)
>> +        PCI_Type1 bridge_specific_data;
>> +    // These are technically not a part of Type 0 / Type 1 structures
>> +    // But I define them in there for ease. Instead, we can use Field Labels
>> +    // to create virtual fields here that point to the correct data
>> +    reg_8 cap_ptr @ 0x34#B;
>> +    reg_8 int_line @ 0x3C#B;
>> +    reg_8 int_pin @ 0x3D#B;
>
>
> Instead of field labels (which only works for mapped data), you can use 
> `computed' fields:
>
> ```
>       computed uint<8> cap_ptr;
>       computed uint<8> int_line;
>       computed uint<8> int_pin;
>
>       method get_cap_ptr = uint<8>:
>       { return header.hdr_layout == 0 ? endpt_specific_data.cap_ptr : /* ... 
> */ ; }
>       method get_int_line = uint<8>: {/*...*/}
>       method get_int_pin  = uint<8>: {/*...*/}
>
>       method set_cap_ptr = (uint<8> cap_ptr) void: { /* ... */ }
>       // ...
> ```
>

It's a lot more verbose than the field labels. But I've made the appropriate 
changes.

>
>> +};
>> +
>> +assert ((PCI_Config_Space {})'size == 0x40#B);
>
>
>
> Regards,
> Mohammad-Reza



reply via email to

[Prev in Thread] Current Thread [Next in Thread]